/********************************************************************************
 * @file    app_ota.c
 * @brief   OTA升级应用逻辑处理
 * 
 * @author  nzttj
 * @date    2025-02-26
 * @version 1.0
 * 
 * Copyright (C) 2025 nzttj
 * 
 * 本软件使用 GNU 通用公共许可证 (GPL) 第 3 版授权。
 * 
 * 您可以自由使用、修改、分发本软件，但必须遵守以下条件：
 * 1. 源代码必须开放，且您修改后的代码也必须以 GPL 许可证发布。
 * 2. 发布或分发本软件时，必须附带本许可证，并提供源代码或获取源代码的方式。
 * 
 * 本软件按“原样”提供，不附带任何担保，使用风险由用户自行承担。
 * 
 ********************************************************************************/

#include "app_ota.h"
#include "app_nvs.h"
#include "hal_nvs.h"
#include "app_iot_ctrl.h"


#include "esp_http_client.h"
#include "esp_https_ota.h"
#include "esp_log.h"
#include "esp_system.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/timers.h"

#include <string.h>

static const char *TAG = "app_ota";
static TaskHandle_t app_ota_handle = NULL;
static app_ota_config_t s_ota_cfg = {0};
static app_ota_server_config_t s_ota_server_cfg = {0};

void app_ota_task(void *param)
{
    ESP_LOGI(TAG, "Starting OTA...");

    app_iot_ctrl_led_flash_start(100);

    esp_http_client_config_t http_config = {
        .url = s_ota_cfg.url,
        // .cert_pem = s_ota_cfg.cert_data,
    };

    esp_err_t ret = esp_https_ota(&http_config);
    if (ret != ESP_OK)
    {
        ESP_LOGE(TAG, "Firmware Upgrades Failed, ret: %d", ret);
        app_iot_ctrl_led_flash_stop();
        app_iot_ctrl_led(app_iot_ctrl_get_device_state()->led_on);
        app_ota_handle = NULL;
        vTaskDelete(NULL);
    }

    hal_nvs_erase_key(APP_NVS_NAMESPACE, APP_NVS_KEY_OTA_CFG);

    ESP_LOGI(TAG, "OTA Success, restarting...");
    vTaskDelay(pdMS_TO_TICKS(500));
    esp_restart();
}

int app_ota_init(app_ota_config_t *cfg)
{
    if (app_ota_handle != NULL)
    {
        ESP_LOGW(TAG, "OTA already initialized");
        return 0;
    }

    memcpy(&s_ota_cfg, cfg, sizeof(app_ota_config_t));

    return xTaskCreate(app_ota_task, "app_ota_task", 2048, NULL, 12, &app_ota_handle) == pdPASS ? 0 : -1;
}

int app_ota_deinit(void)
{
    if (app_ota_handle)
    {
        vTaskDelete(app_ota_handle);
        app_ota_handle = NULL;
    }

    return 0;
}

app_ota_config_t *app_ota_get_cfg(void)
{
    return &s_ota_cfg;
}

app_ota_server_config_t *app_ota_get_server_cfg(void)
{
    return &s_ota_server_cfg;
}
